import redis.asyncio as redis
from redis.asyncio.retry import Retry
from redis.backoff import ExponentialBackoff
from config.settings import settings

# 配置指数退避策略：用于连接失败时的重试间隔计算
# base=2：初始间隔为 2^1=2秒，后续按指数增长（2,4,8...）
# cap=10：最大间隔不超过10秒（避免间隔过大导致长时间等待）
backoff = ExponentialBackoff(base=2, cap=10)

# 配置重试策略：连接失败时自动重试
# retries=3：最多重试3次（生产环境不建议过多重试，避免雪崩）
# 注意：redis-py 4.4.0+ 才支持 retry 参数
retry = Retry(backoff=backoff, retries=3)

# 创建Redis连接池（核心配置）
# 连接池作用：复用连接，减少频繁创建/关闭连接的开销
redis_pool = redis.ConnectionPool(
    host=settings.redis_host,  # Redis服务器地址
    port=settings.redis_port,  # Redis端口（默认6379）
    db=settings.redis_db,  # 选择数据库（默认0）
    password=settings.redis_password,  # 密码（无密码可省略）
    decode_responses=True,  # 自动将Redis返回的bytes解码为str（UTF-8）
    retry=retry,  # 应用重试策略
    socket_timeout=5,  # 读取超时（秒）：避免无限阻塞
    socket_connect_timeout=3,  # 连接超时（秒）：快速失败
    socket_keepalive=True,  # 启用TCP保活机制：维持长连接
    health_check_interval=30,  # 连接健康检查间隔（秒）：定期验证连接有效性
    max_connections=10  # 最大连接数：根据并发量调整（建议不超过Redis最大连接数）
)

# 创建Redis客户端实例（复用连接池）
# 注意：asyncio Redis客户端是单例模式，无需每次创建新实例
redis_client = redis.Redis(connection_pool=redis_pool)


async def get_redis():
    """
    获取Redis异步连接的上下文管理器

    功能：
    1. 从连接池获取一个连接
    2. 提供给调用方使用
    3. 使用完毕后自动归还连接（非关闭，连接池复用）
    """
    # 异步Redis客户端无需手动创建实例，直接使用全局client即可
    # 连接池会自动管理连接的获取与归还
    try:
        yield redis_client
    finally:
        # 异步Redis客户端不需要手动disconnect，连接池会自动维护
        # 仅在极端情况下需要主动释放时使用：await redis_client.aclose()
        pass


async def close_redis():
    """
    应用关闭时释放Redis连接池资源
    调用时机：通常在应用退出钩子中调用（如FastAPI的on_shutdown）
    """
    print('关闭释放Redis连接池资源')
    await redis_pool.disconnect()
